//
// nmea0183.c
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "nmea0183.h"

nmea_desc_group_t g_nmea_desc_group;

#define NMEA_DESC_GROUP()               (&g_nmea_desc_group)

const nmea_desc_group_t * nmea0183_desc_group()
{
    return NMEA_DESC_GROUP();
}

int nmea0183_init()
{
    nmea_desc_group_t * p_desc = NMEA_DESC_GROUP();
    
    memset(p_desc, 0x00, sizeof(nmea_desc_group_t));

    return 0;
}

int nmea0183_parse_gga(const char * p_str)
{
    int pos_ok = 0;
    int dot_cnt;
    int seg_len;
    int deg;
    const char * p_start;
    const char * p_end;
    char buf[32];
    nmea_desc_group_t * p_desc = NMEA_DESC_GROUP();

    dot_cnt = 0;
    p_start = p_str;
    p_end = p_str;
    
    for (;*p_str != '\0'; ++p_str)
    {
        p_end = p_str;
        
        if (',' == *p_end)
        {
            dot_cnt += 1;
            seg_len = p_end - p_start - 1;

            switch (dot_cnt)
            {
                // 时间
                case 2:
                {
                    if ((seg_len >= 6) && (seg_len <= 16))
                    {
                        // 时
                        buf[0] = p_start[1];
                        buf[1] = p_start[2];
                        buf[2] = '\0';
                        p_desc->m_gga_desc.m_time.m_hour = atoi(buf);

                        // 分
                        buf[0] = p_start[3];
                        buf[1] = p_start[4];
                        buf[2] = '\0';
                        p_desc->m_gga_desc.m_time.m_minute = atoi(buf);

                        // 秒
                        memcpy(buf, p_start+5, seg_len-4);
                        buf[seg_len-4] = '\0';
                        p_desc->m_gga_desc.m_time.m_second = atof(buf);
                    }
                
                    break;
                }

                // 纬度
                case 3:
                {
                    if ((seg_len >= 4) && (seg_len <= 32))
                    {
                        // 度
                        buf[0] = p_start[1];
                        buf[1] = p_start[2];
                        buf[2] = '\0';
                        deg = atoi(buf);

                        // 分
                        memcpy(buf, p_start+3, seg_len-2);
                        buf[seg_len-2] = '\0';

                        p_desc->m_gga_desc.m_lat = deg + atof(buf)/60.0;
                    }
                    
                    break;
                }

                // 纬度符号
                case 4:
                {
                    if (seg_len >= 1)
                    {
                        if ('S' == *(p_start + 1))
                        {
                            p_desc->m_gga_desc.m_lat *= -1;
                        }
                    }
                    
                    break;
                }

                // 经度
                case 5:
                {
                    if ((seg_len >= 5) && (seg_len <= 32))
                    {
                        // 度
                        buf[0] = p_start[1];
                        buf[1] = p_start[2];
                        buf[2] = p_start[3];
                        buf[3] = '\0';
                        deg = atoi(buf);

                        // 分
                        memcpy(buf, p_start+4, seg_len-3);
                        buf[seg_len-3] = '\0';

                        p_desc->m_gga_desc.m_lon = deg + atof(buf)/60.0;
                    }
                
                    break;
                }

                // 经度符号
                case 6:
                {
                    if ('W' == *(p_start + 1))
                    {
                        p_desc->m_gga_desc.m_lon *= -1;
                    }
                
                    break;
                }

                // 定位标志
                case 7:
                {
                    if (seg_len >= 1)
                    {
                        if (('1' == *(p_start + 1)) || ('2' == *(p_start + 1)) || ('4' == *(p_start + 1)))
                        {
                            pos_ok = 1;
                            p_desc->m_gga_desc.m_flag = *(p_start + 1);
                        }
                    }
                
                    break;
                }

                // 卫星数
                case 8:
                {
                    if (seg_len > 0)
                    {
                        memcpy(buf, p_start+1, seg_len);
                        buf[seg_len] = '\0';
                        p_desc->m_gga_desc.m_sat_num = atoi(buf);
                    }
                
                    break;
                }

                // 高度
                case 10:
                {
                    if (seg_len > 0)
                    {
                        memcpy(buf, p_start+1, seg_len);
                        buf[seg_len] = '\0';
                        p_desc->m_gga_desc.m_height = atof(buf);
                    }
                
                    break;
                }

                // 高程异常值
                case 12:
                {
                    if (seg_len > 0)
                    {
                        memcpy(buf, p_start+1, seg_len);
                        buf[seg_len] = '\0';
                        p_desc->m_gga_desc.m_hexp = atof(buf);
                    }
                    
                    break;
                }

                default:
                {
                    break;
                }
            }

            p_start = p_end;
        }
    }

    return pos_ok;
}

int nmea0183_parse_rmc(const char * p_str)
{
    int pos_ok = 0;
    int dot_cnt;
    int seg_len;
    int deg;
    const char * p_start;
    const char * p_end;
    char buf[32];
    nmea_desc_group_t * p_desc = NMEA_DESC_GROUP();

    dot_cnt = 0;
    p_start = p_str;
    p_end = p_str;
    
    for (;*p_str != '\0'; ++p_str)
    {
         p_end = p_str;
        
        if (',' == *p_end)
        {
            dot_cnt += 1;
            seg_len = p_end - p_start - 1;

            switch(dot_cnt)
            {
                case 3:
                {
                    if (seg_len >= 1)
                    {
                        if ('A' == *(p_start + 1))
                        {
                            pos_ok = 1;
                        }
                        
                        p_desc->m_rmc_desc.m_flag = *(p_start + 1);
                    }
                
                    break;
                }
            
                case 10:
                {
                    if (seg_len >= 6)
                    {
                        // 日
                        buf[0] = p_start[1];
                        buf[1] = p_start[2];
                        buf[2] = '\0';
                        p_desc->m_rmc_desc.m_ymd.m_day = atoi(buf);

                        // 月
                        buf[0] = p_start[3];
                        buf[1] = p_start[4];
                        buf[2] = '\0';
                        p_desc->m_rmc_desc.m_ymd.m_month = atoi(buf);

                        // 年
                        buf[0] = p_start[5];
                        buf[1] = p_start[6];
                        buf[2] = '\0';
                        p_desc->m_rmc_desc.m_ymd.m_year = atoi(buf) + 2000;
                    }
                
                    break;
                }
            
                default:
                {
                    break;
                }
            }

            p_start = p_end;
        }
    }
    
    return pos_ok;
}

